/*
 * FormUtil.java
 *
 * Created on February 5, 2005, 5:06 PM
 */

package jm.lib.web.util;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import jm.lib.collections.common.KeyValue;
import jm.lib.util.StrUtil;

/**
 * Be very <B>careful</B>, when you use <B>Map</B> to create form, please use
 * <CODE>LinkedHashMap</CODE> or <CODE>SortedMap</CODE> if the display order of
 * items are important.
 * @author Jiming Liu
 */
public class FormUtil {
    final static int TR_ITEM_LEN = 128;
    final static int SELECT_ITEM_LEN = 48;
    final static int TEXTAREA_ITEM_LEN = 128;
    
    final static int BSEARCH_THRESHOLD = 8;
    
    final static public String MULTI_VALUE_SEPERATOR = ";;";
    final static public String ID_PREFIX = "ASKD8_";
    final static public String ID_SUFFIX = "_DJ3S5_";
    
    public static String getElementId(String elementName) {
    	return StrUtil.append(ID_PREFIX, elementName, ID_SUFFIX);
    }
    
    static public String getSelectOne(String name, Collection<String> sels){
        StringBuilder result = new StringBuilder(sels.size() * SELECT_ITEM_LEN);
        getSelectOne(name, sels, null, 0, false, result);
        return result.toString();
    }
    
    static public String getSelectOne(String name, Collection<String> sels, String defaultOption){
        StringBuilder result = new StringBuilder(sels.size() * SELECT_ITEM_LEN);
        getSelectOne(name, sels, defaultOption, 0, false, result);
        return result.toString();
    }
    
    static public void getSelectOne(
            String name
            , Collection<String> sels
            , String defaultOption
            , int size
            , boolean bMultiple
            , StringBuilder buf){
        buf.append("<select name=").append(name);
        if(size > 0) buf.append(" size=").append(size);
        if(bMultiple) buf.append(" multiple");
        buf.append(">\n");
        if(null != defaultOption){
            buf.append("<option value=''>").append(defaultOption).append("</option>\n");
        }
        for(String s: sels){
            buf.append("<option value=\"").append(s).append("\">").append(s).append("</option>\n");
        }
        buf.append("</select>\n");
    }
    
    static public String getSelect(String name, Collection<KeyValue<String,String>> sels){
        StringBuilder result = new StringBuilder(sels.size() * SELECT_ITEM_LEN);
        getSelect(name, sels, null, 0, false, result);
        return result.toString();
    }
    
    static public String getSelect(String name, Collection<KeyValue<String,String>> sels, String defaultOption){
        StringBuilder result = new StringBuilder(sels.size() * SELECT_ITEM_LEN);
        getSelect(name, sels, defaultOption, 0, false, result);
        return result.toString();
    }
    
    static public void getSelect(
            String name
            , Collection<KeyValue<String,String>> sels
            , String defaultOption
            , int size
            , boolean bMultiple
            , StringBuilder buf){
        buf.append("<select name=").append(name);
        if(size > 0) buf.append(" size=").append(String.valueOf(size));
        if(bMultiple) buf.append(" multiple");
        buf.append(">\n");
        if(null != defaultOption){
            buf.append("<option value=''>").append(defaultOption).append("</option>\n");
        }
        for(KeyValue<String,String> s: sels){
            buf.append("<option value=\"").append(s.getKey()).append("\">").append(s.getValue()).append("</option>\n");
        }
        buf.append("</select>\n");
    }
    
    static public String getSelect(String name, Map<String, String> sels){
        return getSelect(name, sels, null);
    }
    
    static public String getSelect(String name, Map<String, String> sels, String defaultOption){
        StringBuilder result = new StringBuilder(sels.size() * SELECT_ITEM_LEN);
        getSelect(name, sels, defaultOption, 0, false, result);
        return result.toString();
    }
    
    static public void getSelect(
            String name
            , Map<String, String> sels
            , String defaultOption
            , int size
            , boolean bMultiple
            , StringBuilder buf){
        buf.append("<select name='").append(name).append('\'');
        if(size > 0) buf.append(" size='").append(String.valueOf(size)).append('\'');
        if(bMultiple) buf.append(" multiple='true'");
        buf.append(">\n");
        if(null != defaultOption){
            buf.append("<option value=''>").append(defaultOption).append("</option>\n");
        }
        for(Entry<String,String> item : sels.entrySet()) {
        	buf.append("<option value='").append(item.getKey()).append("'>").append(item.getValue()).append("</option>\n");
        }
        buf.append("</select>\n");
    }
    
    static public String getTextArea(String name){
        return getTextArea(name, 4, 60, false);
    }
    
    static public String getTextArea(String name, int rows, int cols){
        return getTextArea(name, rows, cols, false);
    }
    
    static public String getTextArea(String name, int rows, int cols, boolean bWithAdjustBtn){
        StringBuilder result = new StringBuilder(bWithAdjustBtn?TEXTAREA_ITEM_LEN*5:TEXTAREA_ITEM_LEN);
        getTextArea(name, rows, cols, bWithAdjustBtn, result);
        return result.toString();
    }
    
    
    /**
     *
     * You should define a css <CODE>taTune</CODE> as follows if <code>bWithAdjustBtn</code> is true,
     * .taTune {width:100px; height=20px; }
     * @param name
     * @param rows
     * @param cols
     * @param bWithAdjustBtn
     * @param buf
     * @return the <code>id</code> value of the textarea
     */
    static public String getTextArea(
            String name
            , int rows
            , int cols
            , boolean bWithAdjustBtn
            , StringBuilder buf){
    	String id = name;
        if(bWithAdjustBtn){
            buf.append("<table><tr><td>\n");
        }
        buf.append("<textarea name='").append(name)
        .append("' rows='").append(String.valueOf(rows))
        .append("' cols='").append(String.valueOf(cols))
        .append("' id='").append(id)
        .append("'>\n");
        buf.append("</textarea>\n");
        if(bWithAdjustBtn){
            buf.append("</td><td>\n");
            buf.append("<button class=taTune onclick=\"adjustTextArea('").append(id).append("', 2)\" id=").append(id).append("B").append(">Broad</button><br/>\n");
            buf.append("<button class=taTune onclick=\"adjustTextArea('").append(id).append("', -2)\" id=").append(id).append("N").append(">Narrow</button><br/>\n");
            buf.append("<button class=taTune onclick=\"adjustTextArea('").append(id).append("', 1)\" id=").append(id).append("H").append(">High</button><br/>\n");
            buf.append("<button class=taTune onclick=\"adjustTextArea('").append(id).append("', -1)\" id=").append(id).append("L").append(">Low</button>\n");
            buf.append("</td></tr></table>\n");
        }
        return id;
    }
    
    static public String getText(String name){
        StringBuilder sb = new StringBuilder(SELECT_ITEM_LEN);
        getText(name, sb);
        return sb.toString();
    }
    static public void getText(String name, StringBuilder buf){
        buf.append("<input type=\"text\" name=\"").append(name).append("\"/>\n");
    }
    static public String getText(String name, String value, int size, int maxLen){
        StringBuilder sb = new StringBuilder(SELECT_ITEM_LEN);
        getText(name, value, size, maxLen, sb);
        return sb.toString();
    }
    public static void getText(String name, String value, int size, int maxLen, StringBuilder buf){
        buf.append("<input type=text name='").append(name)
        .append("' value='").append(value).append("'");
        if(size > 0) buf.append(" size=").append(String.valueOf(size));
        if(maxLen > 0) buf.append(" maxlength=").append(String.valueOf(maxLen));
        buf.append(">\n");
    }
    
    
    static public void getCheckRadio(
            String name
            , Collection<KeyValue<String,String>> values
            , String defaultOption
            , int colPerRow
            , StringBuilder buf
            , boolean bCheckBox
            ){
        getCheckRadio_(name, values, defaultOption, colPerRow, buf, bCheckBox);
    }
    
    static public void getCheckRadio(
            String name
            , Map<String, String> values
            , String defaultOption
            , int colPerRow
            , StringBuilder buf
            , boolean bCheckBox
            ){
        getCheckRadio_(name, values, defaultOption, colPerRow, buf, bCheckBox);
    }
    
    @SuppressWarnings(value={"unchecked"})
    static private void getCheckRadio_(
            String name
            , Object values
            , String defaultOption
            , int colPerRow
            , StringBuilder buf
            , boolean bCheckBox
            ){
        String type = bCheckBox?"checkbox":"radio";
        String checkboxChecked[] = null;
        boolean bBSearch = false;
        if(bCheckBox){
            checkboxChecked= StrUtil.split(defaultOption, MULTI_VALUE_SEPERATOR);
            if(checkboxChecked.length >= BSEARCH_THRESHOLD){
                Arrays.sort(checkboxChecked);
                bBSearch = true;
            }
        }else{
            checkboxChecked = new String[1];
            checkboxChecked[0] = defaultOption;
        }
        
        buf.append("<table id=\"").append(ID_PREFIX).append(name).append(ID_SUFFIX).append("_\">\n");
        int i = 0;
        if(values instanceof Collection){
            Iterator<KeyValue<String,String>> it = ((Collection<KeyValue<String,String>>)values).iterator();
            while(it.hasNext()){
                KeyValue<String,String> item = it.next();
                getCheckRadioItem(name, item.getKey(), item.getValue(), i++, checkboxChecked, colPerRow, buf, type, bCheckBox, bBSearch);
            }
        }else{
            Iterator<Entry<String,String>> it = ((Map<String,String>)values).entrySet().iterator();
            while(it.hasNext()){
                Entry<String,String> item = it.next();
                getCheckRadioItem(name, item.getKey(), item.getValue(), i++, checkboxChecked, colPerRow, buf, type, bCheckBox, bBSearch);
            }
        }
        while(i++ % colPerRow != 0){
            buf.append("<td>&nbsp;</td>");
        }
        buf.append("</tr>\n");
        buf.append("</table>\n");
    }
    
    static private void getCheckRadioItem(
            String name
            , String key
            , String value
            , int index
            , String[] defaultValues
            , int colPerRow
            , StringBuilder buf
            , String type
            , boolean bCheckBox
            , boolean bBSearch){
        if(index % colPerRow == 0){
            if(index > 1) buf.append("</tr>\n");
            buf.append("<tr>");
        }
        buf.append("<td><input name='").append(name).append("' type='").append(type);
        buf.append("' value='").append(value).append('\'');
        if(bCheckBox){
            int pos = -1;
            int len = defaultValues.length;
            for(int i = 0; i < len; i++){
                if(key.equals(defaultValues[i])) {
                	pos = i;
                	break;
                }
            }

            if(pos >= 0) buf.append(" checked='true'");
        }else{
            if(defaultValues[0].equals(value)) buf.append(" checked='true'");
        }
        buf.append(">");
        buf.append(value);
        buf.append("</td>");
    }
    
    public static String getHidden(String name, String value){
        StringBuilder sb = new StringBuilder(SELECT_ITEM_LEN);
        getHidden(name, value, sb);
        return sb.toString();
    }
    public static void getHidden(String name, String value, StringBuilder buf){
        buf.append("<input type='hidden' name='").append(name)
        .append("' value=\"").append(value).append("\">\n");
    }
    
    public static String setAttr(String formName, String itemName, String attrName, String attrValue){
        StringBuilder sb = new StringBuilder();
        return sb.toString();
    }
    public static void setAttr(String formName, String itemName, String attrName, String attrValue, StringBuilder buf){
        buf.append("setElementAttr(\"").append(formName).append("\", \"")
        .append(itemName).append("\", \"").append(attrName).append("\", \"")
        .append(attrValue).append("\");\n");
    }
    
    public static void setAttr(String formName, String itemName, Map<String,String> attrs, StringBuilder buf){
        String attrsVar = "aaaaaaaa";//HtmlUtil.getHtmlUID(itemName);
        buf.append("var ").append(attrsVar).append(" = {\n");
        Iterator<Entry<String,String>> it = attrs.entrySet().iterator();
        boolean bInited = false;
        while(it.hasNext()){
            Entry<String,String> item = it.next();
            if(bInited) buf.append(",");
            buf.append("\"").append(item.getKey()).append("\":\"")
            .append(item.getValue()).append("\"\n");
            bInited = true;
        }
        buf.append("};\n");
        buf.append("setElementAttr(\"").append(formName).append("\", \"")
        .append(itemName).append("\", ").append(attrsVar).append(");\n");
    }
    
    public static void getJSSetValue(String formName, String name, String value, StringBuilder buf){
        buf.append("setValue(\"").append(formName).append("\",\"").append(name)
        .append("\",\"").append(JSUtil.JSEscape(value)).append("\");\n");
    }
    
	/**
	 * 
	 * @param name
	 * @param list
	 * @param value
	 * @return
	 */
	public static String getSelectList(String name, List list, String value) {
		StringBuilder sb = new StringBuilder(128);
		getSelectList(name, list, value, sb);
		return sb.toString();
	}

	public static void getSelectList(String name, List list, String value,
			StringBuilder sb) {
		boolean hasValue = StrUtil.isNotEmpty(value);
		sb.append("<select name=\"").append(name).append("\" size=\"1\">\n");
		for (Iterator iter = list.iterator(); iter.hasNext();) {
			String element = iter.next().toString();
			String encode_element = HtmlUtil.encodeHtml(element);
			sb.append("<option value=\"").append(encode_element).append("\"");
			if (hasValue && element.equalsIgnoreCase(value)) {
				sb.append(" selected=\"true\"");
			}
			sb.append(">").append(encode_element).append("</option>\n");
		}
		sb.append("</select>\n");
	}

	/**
	 * 
	 * @param name
	 * @param map
	 *            key is value of select list and value is label of select list
	 * @param selected_value
	 * @return
	 */
	public static String getSelectList(String name, Map<String, String> map,
			String selected_value) {
		StringBuilder sb = new StringBuilder();
		getSelectList(name, map, selected_value, sb);
		return sb.toString();

	}

	/**
	 * 
	 * @param name
	 * @param map
	 * @param selected_value
	 * @param sb
	 */
	public static void getSelectList(String name, Map<String, String> map,
			String selected_value, StringBuilder sb) {
		boolean hasValue = StrUtil.isNotEmpty(selected_value);
		sb.append("<select name=\"").append(name).append("\" size=\"1\">\n");
		for (Map.Entry<String, String> entry : map.entrySet()) {
			String value = HtmlUtil.encodeHtml(entry.getKey());
			String label = HtmlUtil.encodeHtml(entry.getValue());
			if (StrUtil.isEmpty(label)) {
				label = value;
			}
			sb.append("<option value=\"").append(value).append("\"");
			if (hasValue && selected_value.equalsIgnoreCase(entry.getKey())) {
				sb.append(" selected=\"true\"");
			}
			sb.append(">").append(label).append("</option>\n");
		}
		sb.append("</select>\n");
	}
    
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        //System.out.println (formTextArea ("j", 5, 80));
        // String[] values = {"a", "b", "c", "d", "e", "f", "g"};
        StringBuilder sb = new StringBuilder();
        // Collection<String> c = Arrays.asList(values);
        //CheckRadio("j", ArrayUtil.wrapToList(values), "c;;b", 4, sb, true);
        //CheckRadio("j", ArrayUtil.wrapToList(values), "c", 3, sb, false);
        Map<String,String> m = new LinkedHashMap<String,String> ();
        m.put("a", "aa");
        m.put("b", "bb");
        m.put("c", "cc");
        m.put("d", "dd");
        m.put("e", "ee");
        m.put("f", "ff");
        m.put("g", "gg");
        m.put("h", "hh");
        m.put("i", "ii");
        m.put("j", "jj");
        m.put("k", "kk");
        m.put("l", "ll");
        m.put("m", "mm");
        m.put("n", "nn");
        getCheckRadio("j", m, "c;;d", 3, sb, true);
        
        setAttr("inForm", "question", m, sb);
        getJSSetValue("formname", "aaaa", "dasdfj\"alskd\n\rasdfas",sb);
        System.out.println(sb);
    }
    
}


